package org.concepts.java.core.creation.builder;

import static org.junit.Assert.*;

import org.concepts.java.core.creation.builder.Person.Sex;
import org.junit.Test;

/**
 * Unit test for {@link Person}
 * 
 * @author vvvv
 * 
 */
public class TestPerson {

  @Test
  public void testPersonBasic() {
    Person person = new Person.Builder("Barack", "Basic").build();
    System.out.println(person);

    assertEquals("Barack", person.getFirstName());
    assertEquals("Basic", person.getLastName());
    assertEquals(-1, person.getAge());
    assertEquals(Sex.UNSPECIFIED, person.getSex());
  }

  @Test
  public void testPersonWithAge() {
    Person person = new Person.Builder("Barack", "WithAge").age(48).build();
    System.out.println(person);

    assertEquals("Barack", person.getFirstName());
    assertEquals("WithAge", person.getLastName());
    assertEquals(48, person.getAge());
    assertEquals(Sex.UNSPECIFIED, person.getSex());
  }

  @Test
  public void testPersonWithAgeAndSex() {
    Person person = new Person.Builder("Barack", "WithAgeAndSex").age(48).sex(
        Sex.MALE).build();
    System.out.println(person);

    assertEquals("Barack", person.getFirstName());
    assertEquals("WithAgeAndSex", person.getLastName());
    assertEquals(48, person.getAge());
    assertEquals(Sex.MALE, person.getSex());
  }

  @Test
  public void testPersonSubClass() {
    PersonSubClass personSubClass = (PersonSubClass) new PersonSubClass.Builder(
        "Barack", "SubClass").age(48).build();
  }

  /**
   * Creating subclass of {@link Person} to ensure that we are able to subclass
   * with no problems while using the Builder pattern.
   * 
   * @author vvvv
   * 
   */
  public static class PersonSubClass extends Person {

    private String someAdditionalAttribute = null;

    /**
     * We have declared the constructor as private, as we don't want to allow an
     * subclasses.
     * 
     * @param builder
     */
    private PersonSubClass(Builder builder) {
      super(builder);
      this.someAdditionalAttribute = builder.someAdditionalAttribute;
    }

    @Override
    public String toString() {
      return super.toString() + ", someAdditionalAttribute: "
          + someAdditionalAttribute;
    }

    public static class Builder extends Person.Builder {

      private String someAdditionalAttribute = "default";

      public Builder(String firstName, String lastName) {
        super(firstName, lastName);
      }

      public Builder someAdditionalAttribute(String someAdditionalAttr) {
        this.someAdditionalAttribute = someAdditionalAttr;
        return this;
      }

    }

    /**
     * Some additional attribute that's we are adding in this sub class test of
     * person object.
     * 
     * @return
     */
    public String getSomeAdditionalAttribute() {
      return someAdditionalAttribute;
    }
    

  } // NC - PersonSubClass

}
